/* hardware.c

Copyright (C) Alex S. (mailto: md5sum@alexsp.ru)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details
http://www.gnu.org/licenses/gpl-2.0.html.

You should have received a copy of the GNU General Public License
along with this program in the file gpl-2.0.txt;
if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#include "hardware.h"

const uint8_t percent[]={0,1,2,3,4,5,6,7,9,11,14,18,22,28,35,43,54,67,84,105,131,164,204,255};
static uint8_t current_power=0;
volatile uint8_t sec_flag=0;
int16_t hop03_correct;
uint8_t led_power_max,led_power_min;
uint8_t led_time;
uint8_t led_time_left;

volatile void * save_eep;
volatile void * save_ram;
//volatile uint8_t print_menu_clock=0;

void init_hw(void) __attribute__ ((naked)) __attribute__ ((section (".init6")));
void init_hw(void){
	ACSR=(1<<ACD); //отключим компаратор

	/*Настройки таймера 2 пля управления подсветкой*/
	OCR2=0;
	TCCR2=(1<<WGM20)|(1<< WGM21)|(1<<COM21)|(0<<COM20)|(0<<CS22)|(1<<CS21)|(0<<CS20);
	DDRD&=~(1<<PD7); /*Разрешим выход ШИМ*/

	/*Разрешим внешние прерывания
	int1 - секундные импульсы
	int0 - пропадание питания*/
	MCUCR=(1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(0<<ISC00);
	GICR|=(1<<INT1)|(0<<INT0);
	GIFR=0xff;

	/*Подтяжка входа секунд*/
	DDRD&=~(1<<PD3);
	PORTD|=(1<<PD3);

	/* Подтяжка входов кнопок */
	KEY_DDR&=~(KEY_ENTER|KEY_PLUS|KEY_MINUS);
	KEY_PORT|=(KEY_ENTER|KEY_PLUS|KEY_MINUS);

	/* Подтяжка PD4 для отладки */
	DDRD&=~(1<<PD4);
	PORTD|=(1<<PD4);

#if HUMIDITY==10
	DDRB&=~((1<<5)|(1<<6)); //Порты на вход
	PORTB|=(1<<5)|(1<<6); //Подтянут к +
#endif //HUMIDITY

}

void lcd_backlight_off() {DDRD&=~(1<<PD7);}

/* 0-24 */
void lcd_backlight_on(uint8_t pwr) {
	uint8_t tmp;
	pwr=(pwr>sizeof(percent)?sizeof(percent):pwr);
	DDRD|=(1<<PD7);
	if (pwr>current_power) {
		for (tmp=current_power; tmp<pwr;tmp++) {
#if USE_Watchdog==1
			wdt_reset();
#endif
			_delay_ms(10);
			OCR2=percent[tmp];
		}
	}else if (pwr<current_power){
		for (tmp=current_power; tmp>pwr;tmp--) {
#if USE_Watchdog==1
			wdt_reset();
#endif
			_delay_ms(10);
			OCR2=percent[tmp-1];
		}
		if (pwr==0) lcd_backlight_off();
	}
	current_power=pwr;
}
/*Прерывание вызавается супервизором питания
надо сохраниться пока есть заряд конденсатора*/
ISR(INT0_vect){
	/*Отключаем таймер*/
	TCCR2=0;
	TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
	//	TWCR=0;
	/*Отключаем порты*/
	DDRA=0;
	DDRB=0;
	DDRC=0; /*I2C busy*/
	DDRD=0;
	SFIOR=(1<<PUD); /*Отключили внутреннюю подтяжку портов*/
	PORTA=0;
	PORTB=0;
	PORTC=0;
	PORTD=0;
	/*Записали заранее подготовленный блок*/
	eeprom_write_block((void *)save_ram,(void *)save_eep,sizeof(value_array_t));
	eeprom_busy_wait();
	eeprom_write_byte(&eep_display_mode,display_mode);
	/*Собаку на минимальную задержку*/
#if USE_Watchdog==1
	wdt_enable(WDTO_15MS);
#endif
	/*Ждем пока не появится питание или не разрядится емкость*/
	while ((PORTD&(1<<PD2))==0) {
#if USE_Watchdog==1
		wdt_reset();
#endif
	}
	/*Если питание появилось, то ждем сброса, для полноценой переинициализации*/
	for (;;) {}
}

/* Прерывание 1 раз в секунду */
ISR(INT1_vect){
	sec_flag++;
}

#if HUMIDITY>0
int16_t dew_point(float rh, float t){
/* Расчет по китайской формуле
	float k,dew_point ;

	k = (log10(rh)-2)/0.4343 + (17.62*t)/(243.12+t);
	dew_point = 243.12*k/(17.62-k);
	return (int16_t)(dew_point*100.0);
*/

// Расчет по формуле из вики
	float k,dew_point;
#define A 17.27F
#define B 237.7F
	k=((t*A)/(B+t))+log(rh/100.0F);
	dew_point=(B*k)/(A-k);

	return (int16_t)round(dew_point);
}
#endif
